package com.gezi_game;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.util.Log;
import android.os.Handler;
import android.os.Looper;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactInstanceManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by caoxianliang on 16/11/23.
 */
public class PandaNativeModule extends ReactContextBaseJavaModule {

    private ReactApplicationContext reactContext;

    private static final String REACT_APPLICATION_CLASS_NAME = "com.facebook.react.ReactApplication";
    private static final String REACT_NATIVE_HOST_CLASS_NAME = "com.facebook.react.ReactNativeHost";

    public PandaNativeModule(ReactApplicationContext reactContext) {
        super(reactContext);

        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "PandaNativeModule";
    }

    @ReactMethod
    public void exitApp() {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        getCurrentActivity().startActivity(intent);
        System.exit(0);
    }

    @ReactMethod
    public void openUrl(String url) {
        if (Uri.parse(url).getScheme() == null) {
            Uri.Builder builder = new Uri.Builder();
            url = builder.scheme("http").authority(url).build().toString();
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        if (intent.resolveActivity(this.reactContext.getPackageManager()) != null) {
            this.reactContext.startActivity(intent);
        }
    }

    @ReactMethod
    public void getAppVersionName(Promise promise) {
        String versionName = "";
        try {
            PackageManager pm = this.reactContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(this.reactContext.getPackageName(), 0);
            versionName = pi.versionName;
            if (versionName == null || versionName.length() <= 0) {
                promise.resolve("");
            } else {
                promise.resolve(versionName);
            }
        } catch (Exception e) {
            promise.reject(e);
        }
    }

    @ReactMethod
    public void restartApp() {
        loadBundle();
    }

    private void loadBundle() {
        final Activity currentActivity = getCurrentActivity();

        if (currentActivity == null) {
            return;
        }
        else if (!ReactActivity.class.isInstance(currentActivity)) {
            loadBundleLegacy(currentActivity);
        }
        else {
            try {
                ReactActivity reactActivity = (ReactActivity) currentActivity;
                ReactInstanceManager instanceManager;

                try {
                    Method getApplicationMethod = ReactActivity.class.getMethod("getApplication");
                    Object reactApplication = getApplicationMethod.invoke(reactActivity);
                    Class<?> reactApplicationClass = tryGetClass(REACT_APPLICATION_CLASS_NAME);
                    Method getReactNativeHostMethod = reactApplicationClass.getMethod("getReactNativeHost");
                    Object reactNativeHost = getReactNativeHostMethod.invoke(reactApplication);
                    Class<?> reactNativeHostClass = tryGetClass(REACT_NATIVE_HOST_CLASS_NAME);
                    Method getReactInstanceManagerMethod = reactNativeHostClass.getMethod("getReactInstanceManager");
                    instanceManager = (ReactInstanceManager)getReactInstanceManagerMethod.invoke(reactNativeHost);
                } catch (Exception e) {
                    Field instanceManagerField = ReactActivity.class.getDeclaredField("mReactInstanceManager");
                    instanceManagerField.setAccessible(true);
                    instanceManager = (ReactInstanceManager)instanceManagerField.get(reactActivity);
                }

                final Method recreateMethod = instanceManager.getClass().getMethod("recreateReactContextInBackground");

                final ReactInstanceManager finalizedInstanceManager = instanceManager;
                // reactActivity.runOnUiThread(new Runnable() {
                //     @Override
                //     public void run() {
                //         try {
                //             recreateMethod.invoke(finalizedInstanceManager);
                //         }
                //         catch (Exception e) {
                //             loadBundleLegacy(currentActivity);
                //         }
                //     }
                // });
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                             recreateMethod.invoke(finalizedInstanceManager);
                         }
                         catch (Exception e) {
                             loadBundleLegacy(currentActivity);
                         }
                    }
                });
            } catch (Exception e) {
                loadBundleLegacy(currentActivity);
            }
        }
    }

    private Class tryGetClass(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    private void loadBundleLegacy(final Activity currentActivity) {
        currentActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                currentActivity.recreate();
            }
        });
    }
}
